﻿//2014.4月，分公司报表的辅助插件，包括自动生成表，柱状图、饼图等。
//使用autoBS等方法，须引用jquery  underscore bootstrap.js bootstrap.css
//使用autoLine等画图方法，须引用jquery  highcharts等文件。
//使用autoTable，须引用jquery underscore auto.css文件。建议不使用它
//autoTable autoBSTable 可以代替autoThead autoTbody.它们已经过时，只用在分公司查询的页面。
//autoNy autoNyr需要用到修改过后的 bootstrap文件和样式表。

(function ($, WINDOW) {
    WINDOW.FUNC_TRUE = function () { return false; };
    WINDOW.FUNC_FALSE = function () { return false; };
    //auto的调试组件
    $.auto = {
        //日期格式化的函数
         rqFmt:function(v, r) {
                    return v == null ? '' : v.substr(0, 10);
        },
        fmtDate: function (date, fmt) {
            var o = {
                "M+": date.getMonth() + 1,                 //月份
                "d+": date.getDate(),                    //日
                "h+": date.getHours(),                   //小时
                "m+": date.getMinutes(),                 //分
                "s+": date.getSeconds(),                 //秒
                "q+": Math.floor((date.getMonth() + 3) / 3), //季度
                "S": date.getMilliseconds()             //毫秒
            };
            if (/(y+)/.test(fmt))
                fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
            for (var k in o)
                if (new RegExp("(" + k + ")").test(fmt))
                    fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
            return fmt;
        },
        log: function (msg, id) {
            this._outFunc(msg, '#5BC0DE', '#fff', id);
            $.auto._panel && $.auto._panel.find('.autolog').text(++$.auto._logCount);
        },
        warn: function (msg, id) {
            this._outFunc(msg, '#F0AD4E', '#fff', id);
            $.auto._panel && $.auto._panel.find('.autowarn').text(++$.auto._warnCount);
        },
        error: function (msg, id) {
            this._outFunc(msg, '#D9534F', '#fff', id);
            $.auto._panel && $.auto._panel.find('.autoerror').text(++$.auto._errorCount);
        },
        success: function (msg, id) {
            this._outFunc(msg, '#5CB85C', '#fff', id);
            $.auto._panel && $.auto._panel.find('.autosuccess').text(++$.auto._sucCount);
        },
        clear: function () {
            if ($.auto._debugpanel) {
                $.auto._debugpanel.children().remove();
                $.auto._count = 0;
                $.auto._time = [];
                $.auto._logCount = $.auto._sucCount = $.auto._warnCount = $.auto._errorCount = 0;
                $.auto._panel.find('.label').text(0);
            }
        },
        _outFunc: function (msg, bgColor, color, id) {
            if ($.auto._debugpanel) {
                $.auto._count++;
                var xh = '  ' + String(1000 + $.auto._count).substring(1);
                var now = new Date();
                if (typeof id !== 'undefined') {
                    if (typeof $.auto._time[id] === 'undefined') $.auto._time[id] = [];
                    var lasttime = $.auto._time[id].slice(-1);
                    lasttime.length == 0 ? lasttime = now : lasttime = lasttime[0];
                    $.auto._time[id].push(now);
                    msg = xh + '. ' + $.auto.fmtDate(now, 'hh:mm:ss ') + '(id:' + id + ' >' + ((now.getTime() - lasttime.getTime()) / 1000) + '秒) :' + msg;
                }
                else {
                    msg = xh + '. ' + $.auto.fmtDate(now, 'hh:mm:ss ') + ' :' + msg;
                }
                var div = $('<div>').css({
                    'background-color': bgColor, color: color, 'padding-left': '8px'
                }).html(msg);
                $.auto._debugpanel.append(div);
                div[0].scrollIntoView();
            }
        },

        //message组件
        /*  alert: function (title, msg, option) {
              initAlertPanel();
              var size = {
                  smCss: { width: '300px' },
                  lgCss: { width: '600px' }
              };
              var opt = $.extend({
                  isFooter: false,
                  size: 'sm',     //只能取lg或sm
                  position: 'cm',//position取9种值，上中下分别tmb,左中右为lcr的任意组合。
                  css: {},         //用户定义样式，赋给最外层。比如定义大小。
                  done: null      //点击关闭时的事件,function (thisscope){};
              }, option);
  
              $.auto._alertrPanel.find('.modal-title').html(title).end()
                                  .find('.modal-body').html(msg).end()
                                  .css(size[opt.size + "Css"]).css(opt.css);
              if (!opt.isFooter) {
                  $.auto._alertrPanel.find('.modal-footer').hide();
              }
              //计算左上的距离，并适当在下右方增加空间，显示阴影
              var ww = $(window).width(), wh = $(window).height(),
              dw = $.auto._alertrPanel.width(), dh = $.auto._alertrPanel.height();
              var t = 0, l = 5;
              if (wh > dh) {
                  opt.position.indexOf('m') != -1 && (t = (wh - dh) / 2);
                  opt.position.indexOf('b') != -1 && (t = (wh - dh) - 10);
              }
              if (ww > dw) {
                  opt.position.indexOf('c') != -1 && (l = (ww - dw) / 2);
                  opt.position.indexOf('r') != -1 && (l = (ww - dw) - 10);
              }
              //显示
              $.auto._alertrPanel.css({ left: l, top: t }).show();
              //使之可相对屏幕拖动，透明0.6
              $.auto._alertrPanel.autoDrag({ floatIn: 'screen', handler: '.modal-header', dragOpacity: 0.6 });
              //绑定事件
              $.auto._alertrPanel.off('click');
              if (typeof option !== 'undefined' && _.isFunction(opt.done)) {
                  $.auto._alertrPanel.on('click', '.gbAlert', function () {
                      opt.done();
                  });
              }
          },*/
        //layer的alert,options借用layer的参数
        alert: function (title, msg, options) {
            var opt = $.extend({
                title: title,
                btn: ['我知道了']
            }, options);
            layer.alert(msg, opt);
        },
        //storage保存本地数据，localStorage或cookie
        //key ,value必须是字符串
        storage: {
            //不存在，返回null
            get: function (key) {
                if (window.localStorage) {
                    return JSON.parse(window.localStorage.getItem(key));
                }
            },
            set: function (key, value) {
                if (window.localStorage) {
                    return window.localStorage.setItem(key, _.isString(value) ? value : JSON.stringify(value));
                }
            }
        }
    };
    //将浏览器信息存放于此。navigator.userAgent	"Mozilla/5.0 (Windows NT 6.4; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; rv:11.0) like Gecko"
    $.auto.browser = { ie: null, firefox: null, chrome: null, opera: null, safari: null };// /(msie\s|trident.*rv:)([\w.]+)/
    var ua = navigator.userAgent.toLowerCase();
    if (/msie\s|trident.*rv:/.test(ua))
        $.auto.browser.ie = parseInt(ua.match(/(msie\s|trident.*rv:)([\d.]+)/)[2])
    else if (/firefox/.test(ua))
        $.auto.browser.firefox = parseInt(ua.match(/firefox\/([\d.]+)/)[1])
    else if (/chrome/.test(ua))
        $.auto.browser.chrome = parseInt(ua.match(/chrome\/([\d.]+)/)[1])
    else if (window.opera)
        $.auto.browser.opera = parseInt(ua.match(/opera.([\d.]+)/)[1])
    else if (/safari/.test(ua))
        $.auto.browser.safari = parseInt(ua.match(/version\/([\d.]+)/)[1]);

    //从table\页面元素\jsondata转到excel .需要提前引入filesaver.js 
    (typeof saveTextAs !== 'undefined') && (
    $.auto.Export = function (options) {
        var opt = {
            source: '', //可以是 页面选择器、Jquery对象或数组，不可为空 。
            filename: '导出文件.xls',  //下载的文件名
            sheetname: 'sheet1'
        };
        $.extend(opt, options);
        if (_.isEmpty(opt.source) || _.isEmpty(opt.filename)) return;
        var template = _.template('<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style>table{ border-collapse: collapse;}table td,table th {  border: solid 1px #333;}</style><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name><%= worksheet %></x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><%= content %></body></html>');

        //字符串，则转为jquery对象
        var source = opt.source;
        if (_.isString(opt.source)) source = $(opt.source);

        //是数组
        if (_.isArray(source)) {
            //没数据则返回。
            if (source.length == 0) return;
            var toExcel;
            var $table = $('<table>');
            $table.autoTable({
                data: source,
                prefix: 'v',
                isRownumber: false,
                isFooter: false,
                initClass: ''
            });
            toExcel = "<table>";
            var head = $table.children('thead');
            if (head.length) toExcel += (head.prop("outerHTML"));
            var body = $table.children('tbody');
            if (body.length) toExcel += (body.prop("outerHTML"));
            toExcel += "</table>";
            var ctx = { worksheet: opt.sheetname, content: toExcel };
            saveTextAs(template(ctx), opt.filename);
        }
            //是jquery对象：
        else if (source.jquery) {
            if (source.length == 0) return;
            //1、输出为excel
            var toExcel;
            if (source.is('table')) {
                //对表头和表身的顺序进行调整一下。
                toExcel = "<table>";
                var head = source.children('thead');
                if (head.length) toExcel += (head.prop("outerHTML"));
                var body = source.children('tbody');
                if (body.length) toExcel += (body.prop("outerHTML"));
                toExcel += "</table>";
            }
            else {
                //非表，直接输出即可
                toExcel = source.prop("outerHTML");
            }
            var ctx = { worksheet: opt.sheetname, content: toExcel };
            saveTextAs(template(ctx), opt.filename);
        }
    });

    function initDebugPanel() {
        $(window).bind('hashchange', function () {
            if (window.location.hash.indexOf('#debug') != -1) {
                if (!$.auto._panel) {
                    $.auto._panel = null;
                    $.auto._debugpanel = null;
                    $.auto._count = 0;
                    $.auto._time = [];
                    $.auto._logCount = $.auto._sucCount = $.auto._warnCount = $.auto._errorCount = 0;
                    $('body').append(
                               '<div  style="width: 100%;height:200px;margin:0;"></div>\
                                <div id="autoDebugPanel" class="panel panel-info" style="z-index:30;bottom:0;position:fixed;width: 100%;height:200px;margin:0;">\
									<div class="panel-heading" style="padding: 2px 8px;">\
										 调试窗口<a href="#" class="close pull-right">&times;</a>\
                                         <span class="glyphicon glyphicon-flash"></span><span class="label label-info autolog">0</span>\
                                         <span class="glyphicon glyphicon-ok-circle"></span><span class="label label-success autosuccess">0</span>\
                                        <span class="glyphicon glyphicon-warning-sign"></span><span class="label label-warning autowarn">0</span>\
                                        <span class="glyphicon glyphicon-ban-circle"></span><span class="label label-danger autoerror">0</span>\
										 <a href="javascript:$.auto.clear();" style="margin-left:15px" > <span class="glyphicon glyphicon-trash"></span></a>\
									</div>\
									<div class="panel-body" style="padding:0px;overflow: scroll;height:170px">\
									</div>\
                                </div>');
                    $.auto._panel = $('#autoDebugPanel').hide();
                    $.auto._debugpanel = $.auto._panel.find('.panel-body');
                }
                $.auto._panel.show();
            }
            else {
                $.auto._panel && $.auto._panel.hide();
            }
        });
    }
    initDebugPanel();

    /* function initAlertPanel() {
         if (!$.auto._alertrPanel) {
             $('body').prepend(
 '<div class="modal-dialog" id="autoAlertPanel" style="margin:0px;z-index:20;">\
     <div class="modal-content">\
       <div class="modal-header" style="padding:5px 15px">\
         <button type="button" class="close gbAlert"><span aria-hidden="true">&times;</span></button>\
         <h4 class="modal-title"></h4>\
       </div>\
       <div class="modal-body" style="padding:20px 30px"></div>\
       <div class="modal-footer" style="padding:5px 15px;text-align:center;">\
         <button type="button" class="btn btn-default gbAlert">关闭</button>\
       </div>\
     </div>\
 </div>');
             $.auto._alertrPanel = $('#autoAlertPanel').hide();
             $.auto._alertrPanel.find('.gbAlert').click(function () {
                 $.auto._alertrPanel.hide();
             })
         }
     }
     */
    //dialog的封装
    /* $.fn.dialog = function (options) {
         var me = $(this);
         var opt = {
             title: '',
             backdrop: true,   //bool 或 'static',与bootstrap保持一致
             width: ''  //默认宽度是响应式，在此处可自定义
         };
         $.extend(opt, options);
         var dlg = '';
         if (!me.data('dlg')) {
             dlg = $('\
 <div class="modal fade autodlg">\
   <div class="modal-dialog autocenter">\
     <div class="modal-content">\
       <div class="modal-header">\
         <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>\
         <h4 class="modal-title"></h4>\
       </div>\
       <div class="modal-body">\
       </div>\
       <div class="modal-footer">\
         <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>\
       </div>\
     </div>\
   </div>\
 </div>');
             $('body').prepend(dlg);
             me.show().data('dlg', dlg);
             if (opt.width != '') {
                 dlg.find('.modal-dialog').css('width', opt.width);
             }
             dlg.find('.modal-title').html(opt.title);
             dlg.find('.modal-body').html(me);
             dlg.modal({ backdrop: opt.backdrop });
         } else {
             dlg = me.data('dlg');
             dlg.modal("show");
         }
 
     }*/
    //layer ,options借用layer的参数
    //也可以传入“close”来关闭。
    $.fn.dialog = function (options) {
        var me = $(this);
        if (_.isObject(options)) {
            var opt = $.extend({
                type: 1,
                content: me,
                maxmin: true,//默认最大化
                area: options.width
            }, options);
            var index = layer.open(opt);
            me.data("dialogindex", index);
            var layerContent = me.parents(".layui-layer-content")
            layerContent.height(layerContent.height());
        } else if (_.isString(options)) {
            //目前仅支持close一个命令
            if (options == "close") {
                layer.close(me.data("dialogindex"));
            }
        }

        return me;
    }
    //拖动draggable
    $.fn.autoDrag = function (options) {
        var me = $(this);
        var opt = {
            floatIn: 'page', //page:浮于页面之上。screen:相对于屏幕。 #id：浮于某个页面元素之内,必须用#id的形式
            handler: '',      //在当前元素内部的，拖手的选择器，暂时不考虑元素外部的拖动。
            dragOpacity: 1    //拖动时的透明度
        };
        $.extend(opt, options);
        //设置元素position,外层容器，限制容器，拖手元素
        var posStyle = 'absolute';
        var posContainer = 'body';
        var limitContainer = 'body';
        var handler = me;
        opt.floatIn == 'screen' && (posStyle = 'fixed', limitContainer = window);
        opt.floatIn[0] == '#' && (posContainer = opt.floatIn, limitContainer = opt.floatIn);
        me.css({
            'position': posStyle
        }).prependTo($(posContainer));
        if (opt.handler) {
            handler = me.find(opt.handler);
        }
        handler.css({
            '-moz-user-select': 'none',
            '-webkit-user-select': 'none',
            '-ms-user-select': 'none',
            'user-select': 'none',
            'cursor': 'move'
        });
        //初始化拖动前位置等信息
        var _dragged = false,
            initPos,   //初始位置
            downX, downY,  //鼠标点击位置
            limitX, limitY, //最大的边界，拖动元素不能超过Container。
            orginContainer = { left: 0, top: 0 };
        me.off('.autodrag');

        me.on('mousedown.autodrag', opt.handler, function (e) {
            _dragged = true;
            downX = e.clientX;
            downY = e.clientY;
            initPos = me.position();
            if (opt.dragOpacity < 1 && opt.dragOpacity > 0) {
                me.css('opacity', opt.dragOpacity);
            }
            if (opt.floatIn[0] == '#') {
                orginContainer = $(limitContainer).position();
            }
            limitX = orginContainer.left + $(limitContainer).width() - me.width();
            limitY = orginContainer.top + $(limitContainer).height() - me.height();
            $(document).on('mousemove.autodrag', drag);
        });
        function drag(e) {
            if (_dragged) {
                var curX = initPos.left + (e.clientX - downX),
                    curY = initPos.top + (e.clientY - downY);
                curX = curX < orginContainer.left ? orginContainer.left : (curX > limitX ? limitX : curX);
                curY = curY < orginContainer.top ? orginContainer.topk : (curY > limitY ? limitY : curY);
                me.css({
                    left: curX,
                    top: curY
                });
            }
        }
        $(document).on('mouseup.autodrag', opt.handler, function (e) {
            _dragged = false;
            $(document).off('mousemove.autodrag');
            if (opt.dragOpacity < 1 && opt.dragOpacity > 0) {
                me.css('opacity', 1);
            }
        });
        return me;
    }

    //input全选文字
    $.fn.autoSelectWord = function () {
        var $input = $(this);
        var length = $input.val().length;
        if ($input[0].setSelectionRange) {
            $input[0].focus();
            $input[0].setSelectionRange(0, length);
        } else if ($input[0].createTextRange) {
            var range = $input[0].createTextRange();
            range.collapse(true);
            range.moveEnd('character', length);
            range.moveStart('character', 0);
            range.select();
        }
        $input.focus();
    }
    //自动生成表格。要得到数据行号，请访问tr.rowIndex即可。
    //增加了colgroup控制列。
    //增加了三个事件：loaded,reloaded  cellEdited;
    //外包div {overflow: auto; position: relative; 以及宽度，高度}  
    //表格上增加  position:relative;以防止typeahead插件定位不准确
    $.fn.autoTable = function (options) {
        var me = this;
        var opt = {
            data: [],             //data ,data中不要包含rownum的属性。因为这个是用来控制自动生成的序号的。如果sql中返回rownum,则isRownumber=false,且用ROWNUM来表示该列。
            zeroShowAs: '0',     //分公司报表要求，为0时，不显示，特增加此字段
            nullShowAs: '',
            prefix: '',           //附加前缀。如果不提供，则用table的id.
            isRownumber: true,    //是否显示行号。若显示则header中，要添加对应的列。该列的class='rownum'

            header: [],           //  [{'col|id':[rowspan,colspan,附加属性]},.......],如果锁表头时，有序号列。表头中的序号必须加上 'style:z-index:11;' 以防止被下面的序号覆盖掉。
            header2: [],          //如果折行显示上下表头时，header2表示下表头。 让上下表头有同样多列,下表头不会锁定，做为普通的数据行来显示。 不要使用隐藏列的功能，否则会只隐藏一半,
            headerFields: [],     //上下表头的情况，必须提供这两列才行。
            header2Fields: [],
            omitFields: [],              //忽略的列

            isFooter: true,       //是否显示页脚， 分页时须显示，分页条显示在footer中的。
            isPageable: false,    //是否分页  
            pageNumber: 1,        //初始页码
            pageSize: 20,         //初始页大小
            pageSizeList: [10, 20, 50, 100],   //页大小列表

            sortFields: [],    //需要排序的列
            mergeFields: [],       //纵向合并
            columnsWidths: [],  //指明列宽度，比如[50,50,80,......]。主要是由于360，狗浏览器在编辑时，编辑框会把表格挤变形。所以指明每一列的宽度

            isScrollable: false,   //默认不支持滚动
            freezeFields: [],          //锁定的列，目增加.frzTd样式。
            freezeContainer: window,  //锁定表时的容器。默认是window的滚动，可以是包含表的选择器.比如 #tt_div

            isSelectable: false,

            columns: {},             /*格式化显示列的内容{ name:{formator:function(v,r){ return '';},
                                                                  editor:function(v,r){   //可编辑。注意对于纵向合并单元格的列，只能修改第一行的值。
                                                                                    return {
                                                                                        url: 'xedit.ashx',
                                                                                        kv: { name: r['name'],xh:r['address'] },
                                                                                        field: 'age',
                                                                                        type: 'text'
                                                                                    ````};
                                                                                    } ,
                                                                   tooltip:function(v,r){ return "";}显示在单元格上的提示                 
                                                                  }         
                            ```````````````````````````` }  */
            tooltipOnRow: null,      //鼠标移到行上时，提示的内容。可以是function(row){}
            keydataOnRow: [],         //向tr的行上，绑定上当前行的某些值。比如['SEX']这样，在tr里增加  data-SEX='1'
            editUrl: '',               //统一的更新地址，edit这4个参数必须全部提供，才能有编辑的功能，缺一不可。
            editTable: '',             //指向编辑的表名字
            editKeyFields: [],         //表的主键。更新时的依据。
            editFields: [],           //可编辑的列,要保证field和数据库中字段是对应的。这里优先级比columns.editor低。
            //尤其注意：不要纵向合并单元格的功能混用。 否则只能编辑合并的第一行的值。
            editOn: null,                 //指标哪些行可以编辑，默认是所有行。如果要限制,将第1个参数改为field,表示是哪个列，可以  function (field,r) {return r.NY=='201408';} ,表示年月是201408的行可编辑。 
            editBeforeUpload: null,   //编辑提交前，对值进行验证或处理,返回false，则不提交。function(up,field){ return true;}
            /**  上传到服务器端有 old_   _TALBE  _FIELD 以及 field的值 ，主键列的值*/
            filter: null,                //过滤数据行，返回true,表示保留下来。示例：function(row){ return true;}
            isAnalyse: false,            //是否进行数据分析，像excel一样，选择区域，可以显示相关统计值。 该属性会引起文字不能够选择。
            isSaveable: false,           //最新的不需要引入filesaver.js，同时支持在table上触发export事件，也可以下载。需要后台支持，请求地址是：/api/common/export
                                        //head的写法也得注意了： '序号|rownum': [1, 2, 'style="width:30px"'], 需要这样标注单引号
            initClass: "table table-striped table-bordered table-condensed table-hover" //如果不使用bs的样式，请在这里改成自定义的类，然后在CSS定义样式。cygctable easytable
        };
        $.extend(opt, options);
        opt.prefix || (opt.prefix = me.attr('id'));

        //准备
        //1、是不是第一次调此函数。不是则添加样式，是则移除原事件.
        //如果传入hidedFields, 必须先抹掉。建议如果要保留隐藏列的状态，在load事件中处理，因为那里要重置表宽等。
        if (me.hasClass('autotable')) me.off('.autoTableEvent');
        else me.addClass('autotable ' + opt.initClass);
        opt.hidedFields = [];

        //2、首先确定表各部分及外部container,以及控制列宽。
        var thead = me.find('thead');
        if (thead.length == 0) {
            thead = $('<thead>');
            me.append(thead);
        }
        var tbody = me.find('tbody');
        if (tbody.length == 0) {
            tbody = $('<tbody>');
            me.prepend(tbody);
        }
        var tfoot = me.find('tfoot');
        if (tfoot.length == 0) {
            tfoot = $('<tfoot>');
            me.append(tfoot);
        }
        if (!_.isEmpty(opt.columnsWidths)) {
            var colgroup = me.find('colgroup');
            if (colgroup.length == 0) {
                var colgroup = $('<colgroup>');
                $.each(opt.columnsWidths, function (i, w) {
                    colgroup.append($('<col width="' + w + 'px" />'));
                });
                me.prepend(colgroup);
            }
        }
        var tContainer = $(opt.freezeContainer);  //外部容器
        //3、判断data是否是数组
        if (!_.isArray(opt.data)) {
            $.auto.alert("错误", "传入autoBSTable的数据不是数组，请检查！")
            return;
        }
        //4、过滤列表,设置好行数
        opt.shownData = _.isFunction(opt.filter) ? _.filter(opt.data, opt.filter) : opt.data;
        opt.rowsCount = opt.shownData.length;
        //5、如果用户没有指定字段顺序，表示要按照SQL的顺序，忽略omit后，输出各列。
        //首先把这个列写入到opt.headerFields中去，这样body里，永远只要按照headerFields进行输出就行
        if (opt.shownData.length > 0) {
            if (_.isEmpty(opt.headerFields)) {
                for (key in opt.data[0]) {
                    if (!(_.contains(opt.omitFields, key))) opt.headerFields.push(key);
                }
            }
            //插入序号的列
            if (opt.isRownumber) {
                if (!_.contains(opt.headerFields, 'rownum')) {
                    opt.headerFields.unshift('rownum');
                    if (!_.isEmpty(opt.header2Fields) && !_.isEmpty(opt.header2)) opt.header2Fields.unshift('rownum');
                }
            }
            opt._columnsCount = opt.headerFields.length;
        }
        else { //没有要显示的行，所以隐藏tfoot
            opt._columnsCount = 0;
            opt.isFooter = false;
        }


        //6、判断是否有编辑功能
        opt._isEditable = false;
        if (opt.editFields.length > 0 && opt.editKeyFields.length > 0 && !_.isEmpty(opt.editUrl) && !_.isEmpty(opt.editTable)) {
            opt._isEditable = true;
            me.css('table-layout', 'fixed');
        }

        //模板
        var tmpl_th = _.template('<th <%=id%> <%=colspan%> <%=rowspan%> <%=tag%>><%=title%><%=sort%></th>');
        var tmpl_td = _.template('<td class="<%=prefix%>_<%=field%> <%=frzCls%> <%=editCls%>" <%=title%> data-field="<%=field%>" data-index="<%=index%>" <%=rowspan%> ><%=fd1%><%=value%><%=fd2%></td>');
        var tmpl_autoedit = _.template("<input type='text' class='waitEdit autoEditinput' value='<%=value%>' data-url='<%=url%>' data-kv='<%=kv%>' data-field='<%=field%>' data-old='<%=value%>'>");
        var tmpl_autoAnalyse = _.template('<span title="数值计数/总计数">计数:<span><%=count%>/<%=countAll%></span></span><span title="数值平均值">平均值:<span><%=avg%></span></span><span title="求和" class="bg-info">求和:<span><%=sum%></span></span><span title="最大值">最大值:<span><%=max%></span></span><span title="最小值">最小值:<span><%=min%></span></span>');
        //执行
        //1、表头.如果没输，则自动根据列名生成。
        var tr1head = [];
        if (_.isEmpty(opt.header)) {
            opt.header = [{}];
            _.each(opt.headerFields, function (k, i) {
                k == 'rownum' ? opt.header[0]['序号|rownum'] = [] : opt.header[0][k + "|" + k] = [];
            });
        }
        renderThead(opt.header, tr1head, 1);
        thead.html(tr1head.join(''));
        if (opt.isScrollable) {
            //ie要求transform加在th上。但chrome加在tr上也可以！
            opt._frzThead = thead.find('th')
        }
        //生成下表头,它是要插入tbody的，只生成一次
        var tr2head = [];
        if (!_.isEmpty(opt.header2)) {
            renderThead(opt.header2, tr2head, 2);
        }
        //2、表身
        renderTbody(opt.shownData);
        //3、页脚
        renderTfoot();
        //4、读表头1 的结构
        readHeader1();


        //1、添加表头,btflag区分上下表头
        function renderThead(header, trs, btflag) {
            $.each(header, function (idx, row) {
                btflag == 1 ? trs.push('<tr>') : trs.push('<tr class="autoheader2">');
                for (key in row) {
                    var args = {};
                    var arr = key.split('|');
                    args.title = arr[0]; //标题
                    args.id = ((arr[1] && arr[1][0] != "$") ? 'id="' + opt.prefix + '_' + arr[1] + '" data-field="' + arr[1] + '"' : '');
                    args.colspan = ((row[key][0] && row[key][0] != 1) ? 'colspan="' + row[key][0] + '"' : '');
                    args.rowspan = ((row[key][1] && row[key][1] != 1) ? 'rowspan="' + row[key][1] + '"' : '');
                    //排序图标
                    if (arr[1] && _.contains(opt.sortFields, arr[1])) {
                        args.sort = '<span class="autoSort" style="cursor:pointer" title="排序" data-field="' + arr[1] + '"></span>';
                        args.title = '<span class="autoTdtitle">' + args.title + '</span>';
                    }
                    else {
                        args.sort = "";
                    }
                    //附加信息
                    args.tag = (row[key][2] || '');
                    trs.push(tmpl_th(args));
                }
                trs.push('</tr>')
            });
        }
        //2、添加表内容
        function renderTbody(rows) {
            //确定显示范围
            var start, end;
            start = 0; end = rows.length - 1;
            var slcRows = rows;
            if (opt.isPageable) {
                start = (opt.pageNumber - 1) * opt.pageSize;
                end = Math.min(opt.pageNumber * opt.pageSize - 1, end);
            }
            var trs = [];

            var tr2body = [];
            //对纵向合并的列建立初始的值 ,为了避免生成下表头时，和上表头值一样会丢失一个列，纵向合并现必须区分上下表头的合并
            var vMerge = [{}, {}];
            $.each(opt.mergeFields, function (i, zb) {
                vMerge[0][zb] = Number.NaN;
                vMerge[1][zb] = Number.NaN;
            });
            //循环所有行，生成表身及下表身
            $.each(rows, function (idx, row) {
                if (idx >= start && idx <= end) {
                    function createBeginTr(arrTR) {
                        arrTR.push('<tr ');
                        //行的提示信息
                        opt.tooltipOnRow && _.isFunction(opt.tooltipOnRow) &&
                            arrTR.push('title="' + opt.tooltipOnRow(row) + '" ');
                        //行上绑定关键的列的值。
                        if (opt.keydataOnRow.length > 0) {
                            $.each(opt.keydataOnRow, function (i, k) {
                                _.has(row, k) && arrTR.push('data-' + k + '="' + row[k] + '" ');
                            });
                        }
                        arrTR.push(' >');
                    }
                    //btFlag用以区分上下表头。主要是在纵向合并时，上下表头要分别合并。
                    function createTD(key, index, btFlag) {
                        var args = {};
                        args.prefix = opt.prefix;
                        args.field = key;
                        //格式化显示值zeroShowAs:'0',
                        if (opt.columns[key] && _.isFunction(opt.columns[key].formator))
                            args.value = (opt.columns[key].formator(row[key], row));
                        else
                            args.value = (row[key] === 0 ? opt.zeroShowAs : (row[key] || opt.nullShowAs));//值为0，显示为0. null，不显示。
                        //冻结列
                        if (_.contains(opt.freezeFields, key)) {
                            args.fd1 = "";
                            args.fd2 = "";
                            args.frzCls = 'frzTd';
                        }
                        else {
                            args.fd1 = "";
                            args.fd2 = "";
                            args.frzCls = '';
                        }
                        //列序号:
                        args.index = index;
                        //可编辑,直接输入一个input,同时隐藏掉args.value,格式化列的功能将消失。
                        args.editCls = '';
                        if (opt._isEditable) {
                            if (opt.editOn == null || (_.isFunction(opt.editOn) && opt.editOn(key, row))) {
                                //1、先判断是否有editor
                                if (opt.columns[key] && _.isFunction(opt.columns[key].editor)) {
                                    var editOpt = opt.columns[key].editor(row[key], row);
                                    _.has(editOpt, 'kv') && (editOpt.kv = JSON.stringify(editOpt.kv));
                                    editOpt.value = args.value;
                                    args.fd1 += tmpl_autoedit(editOpt);
                                    args.fd2 += "";
                                    args.value = '';
                                    args.editCls = 'autoEdit';
                                }
                                    //2、再判断是否存在行的edit相关属性。必须有列、主键、请求地址。
                                else if (_.contains(opt.editFields, key) && !(_.isEmpty(opt.editKeyFields)) && opt.editUrl) {
                                    var editOpt = {
                                        url: opt.editUrl,
                                        field: key,
                                        value: args.value
                                    };
                                    var kv = {};
                                    //将主键中的所有值都取出来。
                                    $.each(opt.editKeyFields, function (i, k) {
                                        kv[k] = row[k];
                                    });
                                    editOpt.kv = JSON.stringify(kv);
                                    args.fd1 += tmpl_autoedit(editOpt);
                                    args.fd2 += "";
                                    args.value = '';
                                    args.editCls = 'autoEdit';
                                }
                            }
                        }
                        //td的提示内容
                        if (opt.columns[key] && _.isFunction(opt.columns[key].tooltip))
                            args.title = "title='" + (opt.columns[key].tooltip(row[key], row)) + "'";
                        else
                            args.title = "";
                        //如果该列需要纵向合并，且该列值不同以上面一个值，则其是一个新单元格.向下搜索长度合并。
                        //如果是null，刚不进行合并
                        if (row[key] != null && _.contains(opt.mergeFields, key)) {
                            //不等表示是新值，插入td. 否则表示与上一行相同，忽略生成td。
                            if (row[key] != vMerge[btFlag][key]) {
                                vMerge[btFlag][key] = row[key];
                                var rowspan = 1;
                                while ((idx + rowspan) <= end) {
                                    if (rows[idx + rowspan][key] == vMerge[btFlag][key]) rowspan++;
                                    else break;
                                }
                                args.rowspan = rowspan > 1 ? ('rowspan="' + rowspan + '"') : '';
                            }
                            else
                                //忽略生成td
                                return '';
                        }
                        else {   //不需要合并，则简单显示出来。
                            vMerge[btFlag][key] = row[key];
                            args.rowspan = '';
                        }
                        //输出结果
                        return (tmpl_td(args));
                    }

                    //0、如果显示行号，则补充row['rownum']=idx
                    if (opt.isRownumber) {
                        row['rownum'] = idx + 1;
                    }
                    //1、生成tr的开头部分到相应的变量里
                    createBeginTr(trs);
                    //2、输出到上表身
                    $.each(opt.headerFields, function (i, field) {
                        trs.push(createTD(field, i, 0));
                    })
                    trs.push('</tr>')
                    //如果显示下表身,输出到tr2body中去。
                    if (!_.isEmpty(opt.header2Fields) && !_.isEmpty(opt.header2)) {
                        createBeginTr(tr2body);
                        $.each(opt.header2Fields, function (i, field) {
                            tr2body.push(createTD(field, i, 1));
                        })
                        tr2body.push('</tr>')
                    }
                }
            });
            tbody.html((trs.concat(tr2head, tr2body)).join(''));

            //如果有隐藏列，则隐藏
            if (!_.isEmpty(opt.hidedFields)) {
                $.each(opt.hidedFields, function (i, hidefield) {
                    me.find('tbody>tr>td[data-field=' + hidefield + ']').hide();
                })
            }

            if (opt.isScrollable && !_.isEmpty(opt.freezeFields)) {
                opt._frzTd = tbody.find('.frzTd');
            }
            if (opt.isScrollable) {
                opt._frzThead2 = tbody.find(".autoheader2 th");
            }
            //编辑项
            opt._waitEdit = me.find(".waitEdit");
        }
        //3、添加表脚
        function renderTfoot() {
            if (opt.isFooter) {
                var tr = $('<tr>');
                if (opt.isPageable) {
                    opt.pageCount = parseInt((opt.rowsCount + opt.pageSize - 1) / opt.pageSize);
                    var td = $('<td colspan="' + opt._columnsCount + '"></td>');
                    td.append($('<span>').text('每页'));
                    var psSelect = $('<select>').addClass('psSelect');
                    $.each(opt.pageSizeList, function (i, ps) {
                        if (ps == opt.pageSize) psSelect.append('<option  selected="true">' + ps + '</option>');
                        else psSelect.append('<option>' + ps + '</option>');
                    });
                    psSelect.append('<option value="all">全部</option>');
                    td.append(psSelect);
                    td.append($('<span>').text('条    跳至'));
                    var pnSelect = $('<select>').addClass('pnSelect');
                    for (var i = 1; i <= opt.pageCount; i++) {
                        if (i == opt.pageNumber) pnSelect.append('<option selected="true">' + i + '</option>');
                        else pnSelect.append('<option>' + i + '</option>');
                    }
                    td.append(pnSelect);
                    td.append($('<span>').text('页'));
                    //分隔符
                    //td.append($('<div>').addClass('autoSeparator'));  
                    var pagergroup = $("<div>").addClass('btn-group autoPager');
                    var prebtn = $('<button type="button" class="btn btn-default btn-xs">上一页</button>').data('num', Math.max(opt.pageNumber - 1, 1));
                    opt.pageNumber == 1 && prebtn.addClass("disabled");
                    pagergroup.append(prebtn);
                    var nextbtn = $('<button type="button" class="btn btn-default btn-xs">下一页</button>').data('num', Math.min(opt.pageNumber + 1, opt.pageCount));
                    opt.pageNumber == opt.pageCount && nextbtn.addClass("disabled");
                    pagergroup.append(nextbtn);
                    td.append(pagergroup);
                    //进度条
                    var percent = Math.round(opt.pageNumber / opt.pageCount * 100);
                    var startpercent = Math.round((opt.pageNumber - 1) * opt.pageSize / opt.shownData.length * 100);
                    var endpercent = Math.round(Math.min(opt.pageNumber * opt.pageSize, opt.shownData.length) / opt.shownData.length * 100);


                    var $progress = $('<div>').addClass('progress').attr('title', endpercent + '%');
                    startpercent > 0 && $progress.append($('<div>').addClass('progress-bar progress-bar-info progress-bar-striped').css('width', startpercent + '%'));
                    $progress.append($('<div>').addClass('progress-bar').css('width', (endpercent - startpercent) + '%'));
                    td.append($progress);
                }
                else {
                    var td = $('<td colspan="' + opt._columnsCount + '"></td>');
                    td.append($('<button type="button" class="btn btn-default btn-xs" data-pageable="true">启用分页</button>'));
                }

                if (opt.isSaveable && (typeof saveTextAs !== 'undefined') && _.isFunction(saveTextAs)) td.append($('<button type="button" class="autoSave"><span class="glyphicon glyphicon-list-alt"></span>导出</button>'));
                if (opt.isAnalyse) td.append('<span id="autoAnalyse">');

                tr.append(td);
                tfoot.html(tr);
            }
        }
        //4、读表头结构，以支持隐藏列、表头的锁定列的功能
        function readHeader1() {
            //计算每一列对应哪些表头中的th
            var pos = [[], [], [], [], [], [], [], [], [], []];   //默认表头最大为10行。
            var x = -1, y = -1; //pos是二维数组，表示表头的分布着哪些th
            var thInCol = []; //每一列所包含的th
            var tmp1, tmp2;
            thead.children().each(function (iTR, tr) {
                $(tr).find('th').each(function (jTD, th) {
                    var c = th.colSpan, r = th.rowSpan;
                    for (tmp1 = 1; tmp1 <= c; tmp1++) { //先处理一列，让这一列增加该td
                        for (tmp2 = 1; tmp2 <= r; tmp2++) {
                            //如果当前pos已有值，则向后移一格
                            while (typeof pos[y + tmp2][x + tmp1] !== 'undefined') {
                                x++;
                            }
                            pos[y + tmp2][x + tmp1] = th;
                        }
                        thInCol[x + tmp1] = thInCol[x + tmp1] || [];
                        thInCol[x + tmp1].push(th);
                    }
                    //处理下一个td之前，先修改x的值
                    x = x + th.colSpan;
                });
                ////处理下一个th之前，先修改y的值
                x = -1;
                y++;
            });
            var fieldDict = {}; //每个字段对应的列号,及表头列。  
            //不考虑下表头中出现的列了。
            $.each(opt.headerFields, function (i, field) {
                fieldDict[field] = {
                    index: i,
                    ths: thInCol[i]
                };
            });

            //隐藏列的事件,调用用法：$('#tt').trigger('hide','DWMC,ZS'),锁定的列不隐藏
            me.on('hide.autoTableEvent', function (e, fields) {
                if (typeof fields == 'undefined') return;  ///表格中带datetimepicker时，也向上冒泡产生show 事件，屏蔽之。
                //传入逗号分隔的字符串，或一个数据。每一项是需要隐藏的列。
                var fArr = fields.split(',');
                _.each(fArr, function (f) {
                    if ((_.contains(opt.headerFields,f)) && (!_.contains(opt.hidedFields, f)) && (!_.contains(opt.freezeFields, f))) {
                        opt.hidedFields.push(f);
                        hideCol(f);
                    }
                });
            });
            function hideCol(field) {
                //取该字段的索引
                var fdict = fieldDict[field];
                var hidTD = me.find('tbody>tr>td[data-field=' + field + ']');
                var w = hidTD.width();
                hidTD.data('tdWidth', w);
                _.each(fdict.ths, function (th) {
                    if (th.colSpan > 1) th.colSpan--;
                    else $(th).hide();
                });
                hidTD.hide();
                if (!_.isEmpty(opt.columnsWidths)) {  //如果指定了每个列宽，则必须也隐藏相应的col
                    var i = _.indexOf(opt.headerFields, field);
                    $(colgroup.find("col")[i]).hide();
                }
                me.width(me.width() - w);
            }
            me.on('show.autoTableEvent', function (e, fields) {
                if (typeof fields == 'undefined') return;  ///表格中带datetimepicker时，也向上冒泡产生show 事件，屏蔽之。
                var fArr = fields.split(',');
                _.each(fArr, function (f) {
                    var idx_f = _.indexOf(opt.hidedFields, f)
                    if (idx_f >= 0) {
                        //移除该列
                        //opt.hidedFields = _.reject(opt.hidedFields, function (str) { return str == f; })
                        opt.hidedFields.splice(idx_f, 1);
                        showCol(f);
                    }
                });
            });
            function showCol(field) {
                //取该字段的索引
                var fdict = fieldDict[field];
                _.each(fdict.ths, function (th) {
                    if ($(th).is(':visible')) th.colSpan++;
                    else $(th).show();
                });
                var hidTD = me.find('tbody>tr>td[data-field=' + field + ']');
                hidTD.show();
                if (!_.isEmpty(opt.columnsWidths)) {  //如果指定了每个列宽，则必须也显示相应的col
                    var i = _.indexOf(opt.headerFields, field);
                    $(colgroup.find("col")[i]).show();
                }
                me.width(me.width() + hidTD.data('tdWidth'));
            }
        }

        ///以下为事件绑定
        //单击变色,单击输入框则不变色
        if (opt.isSelectable) {
            me.on('click.autoTableEvent', 'tbody>tr:not(.autoheader2)', {}, function (e) {
                if (!$(e.target).is('input')) {
                    $(this).toggleClass('autoselected');
                }
            });
        }
        //页数跳转
        me.on('click.autoTableEvent', '.autoPager button', {}, function () {
            if (opt.pageNumber != $(this).data('num')) {
                opt.pageNumber = $(this).data('num');
                renderTbody(opt.shownData);
                renderTfoot();
                me.trigger('reloaded');
            }
        });
        me.on('page.autoTableEvent', function (e, page) {
            if (opt.pageNumber != page) {
                opt.pageNumber = page;
                renderTbody(opt.shownData);
                renderTfoot();
                me.trigger('reloaded');
            }
        });
        //下拉页数跳转
        me.on('change.autoTableEvent', '.pnSelect', {}, function () {
            if (opt.pageNumber != parseInt($(this).val())) {
                opt.pageNumber = parseInt($(this).val());
                renderTbody(opt.shownData);
                renderTfoot();
                me.trigger('reloaded');
            }
        });
        //页面大小变化
        me.on('change.autoTableEvent', '.psSelect', {}, function () {
            if ($(this).val() == 'all') {
                opt.isPageable = false;
            }
            else {
                opt.pageSize = parseInt($(this).val());
                opt.pageNumber = 1;
                $(this).data('num', 1);
            }
            renderTbody(opt.shownData);
            renderTfoot();
            me.trigger('reloaded');
        });
        //分页打开或关闭,显示全部移到列表中了
        me.on('click.autoTableEvent', '[data-pageable]', {}, function () {
            if ($(this).data('pageable')) {
                opt.isPageable = true;
                opt.pageNumber = 1;
                renderTbody(opt.shownData);
                renderTfoot();
                me.trigger('reloaded');
            }
        });

        if (opt.sortFields.length) {
            //排序
            me.on('click.autoTableEvent', '.autoSort', {}, function () {
                var field = $(this).data('field');
                var ascSorted = $(this).hasClass('autoSortUp');
                $(this).removeClass('autoSortUp autoSortDown');
                if (ascSorted) {
                    opt.shownData = _.sortBy(opt.shownData, field).reverse();
                    $(this).addClass('autoSortDown');
                } else {
                    opt.shownData = _.sortBy(opt.shownData, field);
                    $(this).addClass('autoSortUp');
                }
                opt.pageNumber = 1;
                renderTbody(opt.shownData);
                renderTfoot();
                me.trigger('reloaded');
            });
            me.on('sort.autoTableEvent', {}, function (e, field) {
                $this = $('#' + opt.prefix + '_' + field).find('.autoSort');
                var ascSorted = $this.hasClass('autoSortUp');
                $this.removeClass('autoSortUp autoSortDown');
                if (ascSorted) {
                    opt.shownData = _.sortBy(opt.shownData, field).reverse();
                    $this.addClass('autoSortDown');
                } else {
                    opt.shownData = _.sortBy(opt.shownData, field);
                    $this.addClass('autoSortUp');
                }
                opt.pageNumber = 1;
                renderTbody(opt.shownData);
                renderTfoot();
                me.trigger('reloaded');
            });
        }
        //如果可编辑，绑定编辑事件，blur时提交，回车转为tab跳转,上下键也能跳转.支持Excel粘贴。
        if (opt._isEditable) {
            me.on("blur.autoTableEvent", '.waitEdit', function () {
                var $input = $(this);
                var field = $input.data('field'),
                    url = $input.data('url'),
                    kv = $input.data('kv'),
                    old = $input.data('old');
                var v = $.trim($input.val()), upKv = _.clone(kv);
                if (v == old.toString()) return;
                //附加上这些值一起上传到后台。这样后台可以用更通用的方法来处理所有的请求。
                upKv[field] = v;
                upKv['old_' + field] = old;
                upKv["_TABLE"] = opt.editTable;
                upKv["_FIELD"] = field;
                //如果有验证，则先验证再提交。
                //同时引发三个事件，附带上传元素，正修改的单元格及成功标志
                if (_.isNull(opt.editBeforeUpload) || (_.isFunction(opt.editBeforeUpload) && opt.editBeforeUpload(upKv, field))) {
                    me.trigger('beforeCellEdited', [upKv, $input]);
                    $.ajax(url, {
                        cache: false, type: 'POST',
                        data: upKv, dataType: 'json',
                        success: function (ret) {
                            $input.data('old', v);
                            //从showdata中找到当前行，把该field的值修改掉
                            _.find(opt.shownData, function (row) {
                                if (_.isMatch(row, kv)) { row[field] = v; return true; }
                                return false;
                            });
                            $input.addClass('cellEdited');
                            me.trigger('cellEdited', [upKv, $input]);
                            me.trigger('afterCellEdited', [upKv, $input, true]);
                        },
                        error: function (XMLHttpRequest, textStatus, errorThrown) {
                            $input.val(old);
                            me.trigger('afterCellEdited', [upKv, $input, false]);
                        }
                    });
                }
            });

            me.on("keydown.autoTableEvent", '.waitEdit', function (event) {
                var newinput = false;
                if (event.keyCode == 13 || event.keyCode == 39) {  //回车及右
                    var idx = opt._waitEdit.index(this);
                    if (idx < opt._waitEdit.length - 1) newinput = $(opt._waitEdit[idx + 1]);
                }
                if (event.keyCode == 38) {  //上
                    var field = $(this).data('field');
                    var list = opt._waitEdit.filter("[data-field='" + field + "']");//获取当前一列所有的编辑项
                    var idx = list.index(this);
                    if (idx > 0) newinput = $(list[idx - 1]);
                }
                if (event.keyCode == 40) {  //下
                    var field = $(this).data('field');
                    var list = opt._waitEdit.filter("[data-field='" + field + "']");
                    var idx = list.index(this);
                    if (idx < list.length - 1) newinput = $(list[idx + 1]);
                }
                if (event.keyCode == 37) {  //左
                    var idx = opt._waitEdit.index(this);
                    if (idx > 0) newinput = $(opt._waitEdit[idx - 1]);
                }
                if (newinput) {
                    newinput.autoSelectWord();
                    newinput[0].scrollIntoView || newinput[0].scrollIntoView();
                    return false;
                }
                return true;
            })
              .on("paste.autoTableEvent", ".waitEdit", function (event) {
                  event.stopPropagation();
                  event.preventDefault();
                  event = event.originalEvent;
                  var cd = event.clipboardData || window.clipboardData;
                  if (!cd) return;//firefox会走这吗？

                  var content = cd.getData("text");
                  var rows = $.auto.browser.firefox ? content.split('\n') : content.split('\r\n');

                  //如果从excel粘贴，则需要弹出最后一个空元素。如果是纯文本，则最后一个非空，不需要弹出。
                  if ($.trim(rows.slice(-1)[0]) == '') {
                      rows.pop();
                  }
                  var xpos = $(this);
                  var ypos = $(this);
                  $.each(rows, function (i, r) {
                      xpos = ypos;
                      var cols = r.split('\t');
                      $.each(cols, function (j, c) {
                          xpos.val($.trim(c)).focus().blur();
                          var idx = opt._waitEdit.index(xpos);
                          if (idx < opt._waitEdit.length - 1) { xpos = $(opt._waitEdit[idx + 1]); }
                          else { return; }  //向后无元素了
                      });
                      var field = ypos.data('field');
                      var list = opt._waitEdit.filter("[data-field='" + field + "']");
                      var index = list.index(ypos);
                      if (index < list.length - 1) ypos = $(list[index + 1]);
                      else return;   //向下无元素了
                  });
              });
        }
        //如果可滚动，绑定事件
        if (opt.isScrollable) {
            tContainer.on('scroll.autoTableEvent', "", function () {
                var top = tContainer.scrollTop();
                var tranTop = "translate(0px," + top + "px)";
                var tranLeft = "translate(" + tContainer.scrollLeft() + "px,0px)";
                opt._frzTd && opt._frzTd.css({
                    "transform": tranLeft
                });
                opt._frzThead && opt._frzThead.css({
                    "transform": tranTop
                });
                if (opt._frzThead2.length > 0) {
                    var offset = opt._frzThead2[0].offsetTop;
                    var head1height = thead.outerHeight();
                    if (top > offset - head1height) {
                        opt._frzThead2.css({
                            "transform": "translate(0px," + (top - offset + head1height) + "px)"
                        });
                    } else {
                        opt._frzThead2.css({
                            "transform": "translate(0px,0px)"
                        });
                    }
                }
            });
        }
        if (opt.isAnalyse) {
            opt._analyse = false;
            var getRC = function getRC($td) {
                return {
                    row: $td.parent('tr').index(),
                    col: $td.data('index')
                };
            };
            var getAnalyse = function ($td1, $td2) {
                var pos1 = getRC($td1), pos2 = getRC($td2);
                var x1, x2, y1, y2;
                x1 = Math.min(pos1.col, pos2.col);
                x2 = Math.max(pos1.col, pos2.col);
                y1 = Math.min(pos1.row, pos2.row);
                y2 = Math.max(pos1.row, pos2.row);
                var arr = [];
                var trs = tbody.children('tr');
                for (var i = x1; i <= x2; i++) {
                    for (var j = y1; j <= y2; j++) {
                        arr.push($.trim($(trs[j]).find("[data-index=" + i + "]")
                                                .addClass('autoAnalyse')
                                                .text()));
                    }
                }
                var min, max, sum, avg, count, countAll;
                min = Number.MAX_VALUE; max = Number.MIN_VALUE;
                sum = count = 0;
                $.each(arr, function (i, v) {
                    v = parseFloat(v, 10);
                    if (!_.isNaN(v)) {
                        min = min > v ? v : min;
                        max = max < v ? v : max;
                        sum = _.add(sum, parseFloat(v, 10));
                        count++;
                    }
                });
                return {
                    min: min,
                    max: max,
                    sum: sum,
                    avg: _.div(sum, count + ".00"),
                    count: count,
                    countAll: arr.length
                };
            };
            var renderAnalyse = function () {
                me.find('.autoAnalyse').removeClass('autoAnalyse');
                $('#autoAnalyse').html(tmpl_autoAnalyse(getAnalyse(opt._starttd, opt._endtd)));
            };
            //tmpl_autoAnalyse
            me.on('mousedown.autoTableEvent', 'tbody td', function () {
                var clicktd = $(this);
                if (!clicktd.hasClass("autoAnalyse")) {
                    opt._starttd = $(this);
                }

                opt._endtd = $(this);
                opt._analyse = true;
                renderAnalyse();
                me.on('mouseenter.analyseEvent', 'td', function () {
                    if (opt._analyse) {
                        opt._endtd = $(this);
                        renderAnalyse();
                    }
                });
            })
              .on('mouseup.autoTableEvent', function () {
                  if (opt._analyse) {
                      opt._analyse = false;
                      me.off('.analyseEvent');
                      me.trigger('afterAnalyseSelected');
                  }
              })
              .on('selectstart', 'tbody', function () {
                  return false;
              })
              .css('-moz-user-select', 'none');
        }
        if (opt.isSaveable) {
            function exportme() {
                /*原来方法
                var v_tbl = $("<table>").autoTable(_.extend({}, opt, {
                    isFooter: false, isPageable: false, editUrl: '',
                    editTable: '', editKeyFields: [], editFields: []
                }));
                $.auto.Export({ source: v_tbl });*/
                var cloneOpt = $.extend(true, {}, opt);
                //直接根据columns.formator来格式化数据到uData里
                var uData = _.pick(cloneOpt, "shownData", "header", "header2",
                        "headerFields", "header2Fields");
                var allfield=_.uniq(opt.header2Fields.concat(opt.headerFields));
                var rownum=1;
                _.each(uData.shownData, function (row) {
                    _.each(allfield, function (key) {
                        if (key == "rownum")
                            row[key] = rownum++;
                        else {
                            if (opt.columns[key] && _.isFunction(opt.columns[key].formator)) {
                                row[key] = opt.columns[key].formator(row[key], row)
                                if (row[key]==null) {
                                    row[key] = "";
                                } else {
                                    row[key] =row[key].replace(/<[^>]+>/g,"");
                                }
                            }
                            else
                                row[key] = (row[key] === 0 ? opt.zeroShowAs : (row[key] || opt.nullShowAs));//值为0，显示为0. null，不显示。
                        }
                    });
                });

                //构造一个下载窗体.
                var $iframe = $('<iframe />');
                var $form = $('<form target="down-file-iframe" method="post" />');
                $form.attr('action', "/api/common/export");
                $form.append("<input  name='d' value='"+JSON.stringify(uData)+ "' />");
                $iframe.append($form);
                $(document.body).append($iframe);
                $form[0].submit();
                $iframe.remove();

            }
            me.on('click.autoTableEvent', '.autoSave', exportme);
            me.on("export.autoTableEvent", exportme);
        }
        //插件结束，返回自身。
        me.data('OriginData', opt);
        me.trigger('loaded');
        return me;
    }
    $.fn.autoBSN = function (options) {
        var opt = {
            format: 'yyyy',
            weekStart: 1,
            autoclose: true,
            startView: 4,
            minView: 4,
            forceParse: false,  //必须设置，否则每次解析错，会变成1899年。
            language: 'zh-CN'
        }
        $.extend(opt, options);
        return this.each(function () {
            var $this = $(this);
            if ($this.is('input[type=text]')) {
                $this.datetimepicker(opt);
            }
        });
    };
    $.fn.autoBSNy = function (options) {
        var opt = {
            format: 'yyyymm',
            weekStart: 1,
            autoclose: true,
            startView: 3,
            minView: 3,
            forceParse: false,  //必须设置，否则每次解析错，会变成1899年。
            language: 'zh-CN'
        }
        $.extend(opt, options);
        return this.each(function () {
            var $this = $(this);
            if ($this.is('input[type=text]')) {
                $this.datetimepicker(opt);
            }
        });
    };
    $.fn.autoBSNyr = function (options) {
        var opt = {
            format: 'yyyy-mm-dd',
            weekStart: 1,
            autoclose: true,
            startView: 2,
            minView: 2,
            forceParse: false,
            language: 'zh-CN'
        }
        $.extend(opt, options);
        return this.each(function () {
            var $this = $(this);
            if ($this.is('input[type=text]')) {
                $this.datetimepicker(opt);
            }
        });
    };


    //不要在按钮的click事件中调用这个方法。它必须在调用一次，且自动绑定上事件。
    //def_fun是一个函数，它必须返回一个jquery的deferred对象。jquery ajax默认返回这个对象。
    //fun_para是向def_fun传入的参数。
    $.fn.ajaxButton = function (fun_def, fun_para) {
        var me = $(this);
        me.on('click', function (event) {
            if (me.hasClass('disabled')) return;
            me.addClass('disabled ');
            fun_def(fun_para).always(function () {
                me.removeClass('disabled ');
            });
        });

    }

    //配合ajaxButton的一个计时显示。支持三个命令'run', 'pause', 'reset'
    $.fn.autoTimer = function (options) {
        var me = $(this);
        //如果是调用, 不传参，工传入一个object
        if (arguments.length == 0 || _.isObject(options)) {
            var opt = {
                text: '已执行<%=time%>秒。',
                interval: 1000  //默认间隔1秒
            }
            $.extend(opt, options);
            opt.count = 1;
            var tmpl = _.template(opt.text);
            opt.timmer = setInterval(function () {
                me.html(tmpl({ time: opt.count++ }));
            }, opt.interval);
            me.data('options', opt);
        }
            //如果是命令,则传入一个string
        else if (_.isString(options) && _.contains(['run', 'pause', 'reset'], options)) {
            var opt = me.data('options');
            if (options == 'pause') {
                if (opt.timmer) {
                    clearInterval(opt.timmer);
                    opt.timmer = null;
                }
            }
            else if (options == 'run') {
                if (!opt.timmer) {
                    opt.timmer = setInterval(function () {
                        me.html(_.template(opt.text, { time: opt.count++ }));
                    }, opt.interval);
                }
            }
            else if (options == 'reset') {
                if (opt.timmer) {
                    clearInterval(opt.timmer);
                    opt.timmer = null;
                    opt.count = 0;
                    me.html(_.template(opt.text, { time: 0 }));
                }
            }
        }
        return me;
    }
    //页面可见性API
    $.auto.pageVisibility = (function () {
        var prefixSupport, keyWithPrefix = function (prefix, key) {
            if (prefix !== "") {
                // 首字母大写
                return prefix + key.slice(0, 1).toUpperCase() + key.slice(1);
            }
            return key;
        };
        var isPageVisibilitySupport = (function () {
            var support = false;
            if (typeof window.screenX === "number") {
                ["webkit", "moz", "ms", "o", ""].forEach(function (prefix) {
                    if (support == false && document[keyWithPrefix(prefix, "hidden")] != undefined) {
                        prefixSupport = prefix;
                        support = true;
                    }
                });
            }
            return support;
        })();

        var isHidden = function () {
            if (isPageVisibilitySupport) {
                return document[keyWithPrefix(prefixSupport, "hidden")];
            }
            return undefined;
        };

        var visibilityState = function () {
            if (isPageVisibilitySupport) {
                return document[keyWithPrefix(prefixSupport, "visibilityState")];
            }
            return undefined;
        };

        return {
            isSupport: typeof isHidden() !== "undefined",
            hidden: isHidden(),
            visibilityState: visibilityState(),
            visibilitychange: function (fn, usecapture) {
                usecapture = undefined || false;
                if (isPageVisibilitySupport && typeof fn === "function") {
                    return document.addEventListener(prefixSupport + "visibilitychange", function (evt) {
                        this.hidden = isHidden();
                        this.visibilityState = visibilityState();
                        fn.call(this, evt);
                    }.bind(this), usecapture);
                }
                return undefined;
            }
        };
    })(undefined);

    //全屏支持，需要引入screenfull.js, 页面添加  :-webkit-full-screen { width: 100%; height: 100%; }
    //el是传入的待全屏的元素，可以是jquery的选择器，或jquery对象。
    $.fn.screenFull = function (el) {
        var me = this;
        me.off(".screenFullEvent");
        me.on("click.screenFullEvent", function () {
            if (screenfull.enabled) {
                if (!screenfull.isFullscreen) {
                    var target = _.isString(el) ? $(el) : el;
                    screenfull.request(target[0]);
                }
                else {
                    screenfull.exit();
                }
            }
            else {
                $.auto.alert("提示", "<p>你的浏览器不支持全屏功能，请你使用较新的浏览器！</p>");
            }
        });
        return me;
    }

    if (typeof Highcharts !== 'undefined') {
        //增加颜色渐变
        //Highcharts.getOptions().colors = $.map(Highcharts.getOptions().colors, function (color) {
        //    return {
        //        radialGradient: { cx: 0.5, cy: 0.4, r: 0.8 },
        //        stops: [
        //            [0, color],
        //            [1, Highcharts.Color(color).brighten(-0.4).get('rgb')] // darken
        //        ]
        //    };
        //});
        //统一的公司标志
        var credits = {
            enabled: false,
            text: '胜利软件',
            href: 'http://10.75.0.125/'
        };
        //绑定3D时的拖动效果
        function drag3DChart(chart) {
            $(chart.container).unbind('.drag3d');
            $(chart.container).bind('mousedown.drag3d touchstart.drag3d', function (e) {
                e = chart.pointer.normalize(e);

                var posX = e.pageX,
                    posY = e.pageY,
                    alpha = chart.options.chart.options3d.alpha,
                    beta = chart.options.chart.options3d.beta,
                    newAlpha,
                    newBeta,
                    sensitivity = 5; // lower is more sensitive

                $(document).bind({
                    'mousemove.drag3d touchdrag.drag3d': function (e) {
                        // Run beta
                        newBeta = beta + (posX - e.pageX) / sensitivity;
                        newBeta = Math.min(100, Math.max(-100, newBeta));
                        chart.options.chart.options3d.beta = newBeta;

                        // Run alpha
                        newAlpha = alpha + (e.pageY - posY) / sensitivity;
                        newAlpha = Math.min(100, Math.max(-100, newAlpha));
                        chart.options.chart.options3d.alpha = newAlpha;
                        var series = chart.series;
                        $.each(series, function (i, s) {

                            s.update({}, false);
                        })
                        chart.redraw(false);
                    },
                    'mouseup touchend': function () {
                        $(document).unbind('.drag3d');
                    }
                });
            });
        }
        //显示原始数据，未实现可编辑
        function showChartdata(chart, isEditable) {
            $(chart.container).unbind('.editdata');
            $(chart.container).bind("dblclick.editdata", function () {
                var nr = "<div style='height:200px;overflow:auto'>";
                $.each(chart.series, function (i, s) {
                    //if (isEditable) {
                    //暂时不实现修改数据的功能了。需要重新解析修改后的结果，再重绘chart.
                    //}
                    //else {
                    nr += '<p>' + s.name + "</p>";
                    nr += '<p>' + _.pluck(s.data, 'y').join(',') + "</p>";
                    //}
                });
                nr += '</div>';
                $.auto.alert('图表的原始数据', nr);
            });
        }
        //柱状图  [{name:'指标名',data:[指标值.......]}， {name:'指标名',data:[指标值.......]}]
        $.fn.autoColumn = function (options) {
            var opt = {
                title: '',
                subtitle: '',
                categories: [],      //格式为['一月','二月'.....]
                data: [],
                isStack: false,
                yText: '',
                yUnit: '',
                xText: '',
                enable3D: false,
                legendEnable: true,
                isDataLabel: true,
                isEditable: false,
                highOption: null   //可以传入highCharts的标准配置,以达到自定义图表的功能

            };
            $.extend(opt, options);
            if (opt.yUnit) {
                opt.yUnit = '(' + opt.yUnit + ')';
            }
            if (opt.isStack) {
                $.each(opt.data, function (i, d) {
                    d.stack = 'mystack';
                });
            }
            //定义好传入highcharts的参数
            var hOpt = {
                chart: {
                    renderTo: this[0],
                    type: 'column',
                    borderWidth: 0,
                    options3d: {
                        enabled: opt.enable3D,
                        viewDistance: 25,
                        alpha: 0,
                        beta: 20,
                       
                    }
                },
                series: opt.data,
                plotOptions: {
                    column: {
                        stacking: opt.isStack ? 'normal' : null,
                        depth: 25,
                        allowPointSelect: true,
                        cursor: 'pointer',
                        dataLabels: {
                            enabled: opt.isDataLabel
                        }
                    }
                },
                title: {
                    text: opt.title
                },
                subtitle: {
                    text: opt.subtitle
                },
                xAxis: {
                    title: { text: opt.xText },
                    categories: opt.categories
                },
                yAxis: {
                    title: {
                        text: opt.yText + opt.yUnit.replace('<sup>', '^').replace('</sup>', ''),
                        rotation: 0,
                        y: -15,
                        margin: -60,
                        align: 'high',
                        style: { "color": "#aaa" }
                    }
                },
                legend: {   //图例
                    enabled: opt.legendEnable,
                    align: 'right',
                    verticalAlign: 'middle',
                    layout: 'vertical'

                },
                credits: credits
            };
            //用用户定义的属性覆盖默认定义值
            if (opt.highOption) {
                $.extend(hOpt, opt.highOption);
            }
            var chart = new Highcharts.Chart(hOpt);
            //允许拖动
            if (opt.enable3D) {
                drag3DChart(chart);
            }
            showChartdata(chart, opt.isEditable);
            return chart;
        }
        //线图，格式为同柱状图
        $.fn.autoLine = function (options) {
            var opt = {
                title: '',
                subtitle: '',
                categories: [],      //格式为['一月','二月'.....]
                data: [],
                isFilled: false,
                yText: '',
                yUnit: '',
                xText: '',
                tickInterval: 'auto', //auto自动调整，0全部显示，其它整数为间隔值
                enable3D: false,
                legendEnable: true,
                isDataLabel: true,
                isEditable: false,
                highOption: null   //可以传入highCharts的标准配置,以达到自定义图表的功能
            };
            $.extend(opt, options);
            if (opt.yUnit) {
                opt.yUnit = '(' + opt.yUnit + ')';
            }
            //定义好传入highcharts的参数
            var hOpt = {
                chart: {
                    renderTo: this[0],
                    type: opt.isFilled ? 'area' : 'line',
                    borderWidth: 0,
                    options3d: {
                        enabled: opt.enable3D,
                        depth: 35,
                        viewDistance: 25,
                        alpha: 0,
                        beta: 20
                    }
                },
                plotOptions: {
                    line: {
                        dataLabels: {
                            enabled: opt.isDataLabel
                        },
                        depth: 35,
                        enableMouseTracking: true
                    },
                    area: {
                        dataLabels: {
                            enabled: true
                        },
                        depth: 35,
                        enableMouseTracking: true
                    }
                },
                series: opt.data,
                xAxis: {
                    title: { text: opt.xText },
                    categories: opt.categories,
                    tickInterval: opt.tickInterval == 'auto' ? 1 : opt.tickInterval + 1  //此处参考了echart的规则。0时，连续， 为1时，跳跃一个，比如1 3 5
                },
                yAxis: {
                    title: {
                        text: opt.yText + opt.yUnit.replace('<sup>', '^').replace('</sup>', ''),
                        rotation: 0,
                        y: -15,
                        margin: -60,
                        align: 'high',
                        style: { "color": "#aaa" }
                    }
                },
                title: {
                    text: opt.title
                },
                subtitle: {
                    text: opt.subtitle
                },
                legend: {   //图例
                    enabled: opt.legendEnable,
                    align: 'right',
                    verticalAlign: 'middle',
                    layout: 'vertical'
                },
                credits: credits
            };
            //用用户定义的属性覆盖默认定义值
            if (opt.highOption) {
                $.extend(hOpt, opt.highOption);
            }
            var chart = new Highcharts.Chart(hOpt);
            //允许拖动
            if (opt.enable3D) {
                drag3DChart(chart);
            }
            showChartdata(chart, opt.isEditable);
            return chart;

        };
        //data是数组，格式为：[ {name:'一月',y:'10',sliced: true,selected: true},{name:'二 月',y:'5'}] 
        //                  或[['一月',10]，['二月',5]]   
        $.fn.autoPie = function (options) {
            var opt = {
                title: '',
                subtitle: '',
                zbname: ' ', //指标名
                data: [],
                enable3D: false,
                legendEnable: true,
                isEditable: false,
                isRing: false,
                highOption: null   //可以传入highCharts的标准配置,以达到自定义图表的功能

            };
            $.extend(opt, options);

            //定义好传入highcharts的参数
            var hOpt = {
                chart: {
                    renderTo: this[0],
                    type: 'pie',
                    borderWidth: 0,
                    plotBackgroundColor: null,
                    plotBorderWidth: null,
                    plotShadow: false,
                    options3d: {
                        enabled: opt.enable3D,
                        depth: 35,
                        alpha: 45,
                        viewDistance: 25,
                        beta: 0
                    },
                    events: {
                        redraw: function () { console.log('redraw') }
                    }
                },
                plotOptions: {
                    pie: {
                        allowPointSelect: true,
                        cursor: 'pointer',
                        startAngle: 0,
                        endAngle: 360,
                        dataLabels: {
                            enabled: true,
                            color: '#000000',
                            connectorColor: '#000000',
                            format: '<b>{point.name}</b>: {point.percentage:.1f} %'
                        },
                        depth: 35,
                        innerSize: opt.isRing ? '60%' : '',
                        showInLegend: opt.legendEnable
                    }
                },
                series: [{
                    name: opt.zbname,
                    data: opt.data
                }],
                title: {
                    text: opt.title
                },
                subtitle: {
                    text: opt.subtitle
                },
                legend: {   //图例
                    enabled: opt.legendEnable,
                    align: 'right',
                    verticalAlign: 'middle',
                    layout: 'vertical'

                },
                credits: credits
            };
            //用用户定义的属性覆盖默认定义值
            if (opt.highOption) {
                $.extend(hOpt, opt.highOption);
            }
            var chart = new Highcharts.Chart(hOpt);
            //允许拖动
            if (opt.enable3D) {
                drag3DChart(chart);
            }
            showChartdata(chart, opt.isEditable);
            return chart;
        };
    }
    if (typeof echarts !== 'undefined') {
        //柱状图  [{name:'指标名',data:[指标值.......]}， {name:'指标名',data:[指标值.......]}]
        $.fn.autoColumn = function (options) {
            var opt = {
                title: '',
                subtitle: '',
                categories: [],      //格式为['一月','二月'.....]
                data: [],
                isStacked: false,
                yText: '',
                yUnit: '',
                xText: '',
                legendEnable: true,
                isDataLabel: true,
                isEditable: false
            };
            $.extend(opt, options);
            if (opt.yUnit) {
                opt.yUnit = '(' + opt.yUnit + ')';
            }
            var legends = [];
            $.each(opt.data, function (i, d) {
                d.type = 'bar';
                legends.push(d.name);
                if (opt.isStacked) {
                    d.stack = 'mystack';
                }
            });

            var chart = echarts.init(this[0]);
            chart.setOption({
                title: {
                    x: 'center',
                    text: opt.title,
                    subtext: opt.subtitle
                },
                tooltip: {
                    trigger: 'item',
                    formatter: '{b} <br/>{a} : {c}' + opt.yUnit
                },
                legend: opt.legendEnable ? {
                    data: legends,
                    orient: 'vertical',
                    x: 'right',
                    y: 'center'
                } : null,
                toolbox: {
                    show: true,
                    feature: {
                        dataZoom: {
                            show: true,
                            title: {
                                dataZoom: '区域缩放',
                                dataZoomReset: '区域缩放后退'
                            }
                        },
                        dataView: { show: true, readOnly: opt.isEditable, lang: ['图表的原始数据', '关闭', '刷新图形'] },
                        magicType: { show: true, type: ['line', 'bar'] },
                        saveAsImage: { show: true }
                    }
                },
                xAxis: [
                    {
                        type: 'category',
                        name: opt.xText,
                        data: opt.categories
                    }
                ],
                yAxis: [
                    {
                        name: opt.yText + opt.yUnit,
                        type: 'value'
                    }
                ],
                itemStyle: {
                    normal: {
                        label: {
                            show: opt.isDataLabel,
                        }
                    }
                },
                series: opt.data
            });
            return chart;
        }

        $.fn.autoLine = function (options) {
            var opt = {
                title: '',
                subtitle: '',
                categories: [],      //格式为['一月','二月'.....]
                data: [],
                isFilled: false,    //是否下面区块填充
                yText: '',
                yUnit: '',
                xText: '',
                tickInterval: 'auto', //auto自动调整，0全部显示，其它整数为间隔值
                legendEnable: true,
                isDataLabel: true,
                isEditable: false
            };
            $.extend(opt, options);
            if (opt.yUnit) {
                opt.yUnit = '(' + opt.yUnit + ')';
            }
            var legends = [];
            $.each(opt.data, function (i, d) {
                d.type = 'line';
                if (opt.isFilled) {
                    d.itemStyle = {
                        normal: {
                            areaStyle: { type: 'default' }
                        }
                    }
                }
                legends.push(d.name);
                if (opt.isStacked) {
                    d.stack = 'mystack';
                }
            });

            var chart = echarts.init(this[0]);
            chart.setOption({
                title: {
                    x: 'center',
                    text: opt.title,
                    subtext: opt.subtitle
                },
                tooltip: {
                    trigger: 'item',
                    formatter: '{b} <br/>{a} : {c}' + opt.yUnit
                },
                legend: opt.legendEnable ? {
                    data: legends,
                    orient: 'vertical',
                    x: 'right',
                    y: 'center'
                } : null,
                toolbox: {
                    show: true,
                    feature: {
                        dataZoom: {
                            show: true,
                            title: {
                                dataZoom: '区域缩放',
                                dataZoomReset: '区域缩放后退'
                            }
                        },
                        dataView: { show: true, readOnly: opt.isEditable, lang: ['图表的原始数据', '关闭', '刷新图形'] },
                        magicType: { show: true, type: ['line', 'bar'] },
                        saveAsImage: { show: true }
                    }
                },
                xAxis: [
                    {
                        type: 'category',
                        name: opt.xText,
                        data: opt.categories,
                        axisTick: { interval: opt.tickInterval }
                    }
                ],
                yAxis: [
                    {
                        name: opt.yText + opt.yUnit,
                        type: 'value'
                    }
                ],
                itemStyle: {
                    normal: {
                        label: {
                            show: opt.isDataLabel,
                        }
                    }
                },
                series: opt.data
            });
            return chart;
        }
        //data是数组，格式为：[ {name:'一月',y:'10',sliced: true,selected: true},{name:'二 月',y:'5'}] 
        //                  或[['一月',10]，['二月',5]]   
        $.fn.autoPie = function (options) {
            var opt = {
                title: '',
                subtitle: '',
                zbname: ' ', //指标名
                data: [],
                legendEnable: true,
                isRing: false,
                isEditable: false
            };
            $.extend(opt, options);
            var seriesData = [{
                name: opt.zbname,
                type: 'pie',
                radius: opt.isRing ? ['60', '70%'] : ['0%', '70%'],
                center: ['50%', '60%'],
                itemStyle: {
                    normal: {
                        label: {
                            show: true,
                            position: 'outer',
                            formatter: '{b} {d} %'
                        }
                    }
                },
                data: []
            }];
            var legends = [];
            $.each(opt.data, function (i, d) {
                legends.push(d.name);
                if (_.isArray(d)) {
                    seriesData[0].data.push({
                        value: d[1],
                        name: d[0]
                    })
                }
                else if (_.isObject(d)) {
                    seriesData[0].data.push({
                        value: d.y,
                        name: d.name
                    })
                }

            });

            var chart = echarts.init(this[0]);
            chart.setOption({
                title: {
                    x: 'center',
                    text: opt.title,
                    subtext: opt.subtitle
                },
                tooltip: {
                    trigger: 'item',
                    formatter: '{b} <br/>{a} : {c}'
                },
                legend: opt.legendEnable ? {
                    data: legends,
                    orient: 'vertical',
                    x: 'right',
                    y: 'center'
                } : null,
                toolbox: {
                    show: true,
                    feature: {
                        dataView: { show: true, readOnly: opt.isEditable, lang: ['图表的原始数据', '关闭', '刷新图形'] },
                        saveAsImage: { show: true }
                    }
                },
                calculable: false,
                series: seriesData
            });
            return chart;
        };
    }
    //修正js中浮点数运算时产生精度误差，只保留最大精度,
    _.mixin({
        div: function () {
            if (arguments.length == 1) {
                return parseFloat(arguments[0]);
            }
            else if (arguments.length > 1) {
                var m, r = arguments[0];
                try { m = arguments[0].toString().split(".")[1].length; } catch (e) { m = 0; }
                for (var i = 1; i < arguments.length; i++) {
                    try { t = arguments[i].toString().split(".")[1].length; } catch (e) { t = 0; }
                    m = t > m ? t : m;
                    r /= (arguments[i]);
                }
                return Number(r.toFixed(m));
            }
        },
        mul: function () {
            if (arguments.length == 1) {
                return parseFloat(arguments[0]);
            }
            else if (arguments.length > 1) {
                var l = 0, m = 0, r = 1;
                for (var i = 0; i < arguments.length; i++) {
                    try { t = arguments[i].toString().split(".")[1].length; } catch (e) { t = 0; }
                    m = t > m ? t : m;
                    r *= arguments[i];
                }
                return Number(r.toFixed(m));
            }
        },
        add: function () {
            if (arguments.length == 1) {
                return parseFloat(arguments[0]);
            }
            else if (arguments.length > 1) {
                var l = 0, m = 0, r = 0;
                for (var i = 0; i < arguments.length; i++) {
                    try { t = arguments[i].toString().split(".")[1].length; } catch (e) { t = 0; }
                    m = t > m ? t : m;
                    r += arguments[i];
                }
                return Number(r.toFixed(m));
            }
        },
        sub: function () {
            if (arguments.length == 1) {
                return parseFloat(arguments[0]);
            }
            else if (arguments.length > 1) {
                var m, r = arguments[0];
                try { m = arguments[0].toString().split(".")[1].length; } catch (e) { m = 0; }
                for (var i = 1; i < arguments.length; i++) {
                    try { t = arguments[i].toString().split(".")[1].length; } catch (e) { t = 0; }
                    m = t > m ? t : m;
                    r -= (arguments[i]);
                }
                return Number(r.toFixed(m));
            }
        }
    });

    //关于采油工程系统的需要，特别增加的变量，方法，事件的封装
    WINDOW.WEB_SOCKET_SWF_LOCATION = "/websocketjs/WebSocketMain.swf";
    WINDOW.SERVERPATH = "http://10.75.241.125/ZYCYGC";
    $.auto.WS = function (path) {
        var ws = { send: function () { } };
        try {
            ws = new WebSocket('ws://10.75.241.125:8008/' + path);
        }
        catch (ex) {
            console.log("创建websocket时错误，错误原因:" + ex.toString());
        }
        return ws;
    };
    toastr.options = {
        "closeButton": true,
        "progressBar": true,
        "positionClass": "toast-bottom-right"
    };
    $(document).ajaxError(function (event, jqxhr, settings, exception) {
        var content = jqxhr.responseText;
        console.log(event);
        console.log(jqxhr);
        console.log(settings);
        console.log(exception);
        var pos = content.indexOf("\n");
        var left, right;
        if (pos > 0) {
            $.auto.alert('出错提示', '<h4> 操作失败，请及时联系项目组或在采油工程QQ群内反映！</h4><hr />' +
           '<dl style="overflow-y: auto;max-height: 250px;">\
                <dt>'+ content.substring(0, pos) + '</dt>\
                <dd><pre>' + content.substring(pos + 1) + '</pre></dd>\
            </dl>');
        }
        else {
            $.auto.alert('出错提示', '<h4> 操作失败，请及时联系项目组或在采油工程QQ群内反映！</h4><hr />' +
             '<dl style="overflow-y: auto;max-height: 250px;">\
                <dt>出错信息</dt>\
                <dd><pre>' + jqxhr.responseText + '</pre></dd>\
            </dl>');
        }

    });
})(jQuery, window);

